﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TerhelesEloszto.Common;

namespace TerhelesEloszto.Engine
{
	/// <summary>
	/// Évközi feladatot reprezentáló osztály.
	/// </summary>
	class Task : ITask
	{
		#region ITask Members

		/// <summary>
		/// A feladat neve.
		/// </summary>
		public string Name
		{
			get { return name; }
			set { name = value; }
		}

		/// <summary>
		/// A feladathoz tartozó tantárgy.
		/// </summary>
		public IFact RelatedFact
		{
			get { return relatedFact; }
			set { relatedFact = value; }
		}

		/// <summary>
		/// A feladat típusa.
		/// </summary>
		public ITaskType Type
		{
			get { return type; }
			set { type = value; }
		}

		/// <summary>
		/// A feladathoz tartozó időintervallumok.
		/// </summary>
		public List<IInterval> TimeIntervals
		{
			get { return timeIntervals; }
			set { timeIntervals = value; }
		}

		/// <summary>
		/// A feladat elvégzéséhez szükséges szakmai preferenciák.
		/// </summary>
		public List<ISkill> RequiredSkills
		{
			get { return requiredSkills; }
			set { requiredSkills = value; }
		}

		/// <summary>
		/// Azon oktatók listája, akik a feladatot elvégezhetik a szakmai preferenciáik alapján.
		/// </summary>		
		public List<ITeacher> PossibleTeachers
		{
			get { return possibleTeachers; }
			set { possibleTeachers = value; }
		}

		/// <summary>
		/// A feladathoz hozzárendelt oktató.
		/// </summary>
		public ITeacher RelatedTeacher
		{
			get { return relatedTeacher; }
			set { relatedTeacher = value; }
		}


		/// <summary>
		/// A feladat heti óraszáma.
		/// </summary>
		public int Hours
		{
			get { return hours; }
			set { hours = value; }
		}

		/// <summary>
		/// A taskhoz tartozó szemeszter.
		/// </summary>
		public SemesterType Semester
		{
			get { return semester; }
			set { semester = value; }
		}

		/// <summary>
		/// A feladat azonosítója.
		/// </summary>
		public int ID
		{
			get { return id; }
		}

		/// <summary>
		/// A feladat elvégzéséhez szükséges szakmai preferenciák.
		/// </summary>
		/// <returns>A feladat elvégzéséhez szükséges szakmai preferenciák.</returns>
		public List<ISkill> GetRequiredSkills()
		{
			return RequiredSkills;
		}

		/// <summary>
		/// Azon oktatók listája, akik a feladatot elvégezhetik a szakmai preferenciáik alapján.
		/// </summary>
		/// <returns>Azon oktatók listája, akik a feladatot elvégezhetik a szakmai preferenciáik alapján.</return
		public List<ITeacher> GetPossibleTeachers()
		{
			return PossibleTeachers;
		}

		/// <summary>
		/// A feladathoz hozzárendelt oktató.
		/// </summary>
		/// <returns>A feladathoz hozzárendelt oktató.</returns>
		public ITeacher GetRelatedTeacher()
		{
			return RelatedTeacher;
		}

		/// <summary>
		/// A feladathoz tartozó tantárgy.
		/// </summary>
		/// <returns>A feladathoz tartozó tantárgy.</returns>
		public IFact GetRelatedFact()
		{
			return RelatedFact;
		}

		/// <summary>
		/// A feladat típusa.
		/// </summary>
		/// <returns>A feladat típusa.</returns>
		public new ITaskType GetType()
		{
			return Type;
		}

		/// <summary>
		/// A feladathoz tartozó időintervallumok.
		/// </summary>
		/// <returns>A feladathoz tartozó időintervallumok.</returns>
		public List<IInterval> GetTimeIntervals()
		{
			return TimeIntervals;
		}

		/// <summary>
		/// A task két heti összes óraszámát adja vissza.
		/// </summary>
		/// <returns>A task két heti összes óraszámát adja vissza.</returns>
		public int GetHoursOnTwoAWeek()
		{
			if( !type.HasInterval ) return hours * 2;
			else
			{
				int h = 0;
				foreach( IInterval iv in timeIntervals )
				{
					h += ( iv.EndHour - iv.BeginHour );
				}
				return h;
			}
		}

		/// <summary>
		/// Igaz értékkel tér vissza ha ütközik a másik taskkal (a szemesztert nem vizsgálja.)
		/// </summary>
		/// <param name="other">A másik task.</param>
		/// <returns> Igaz értékkel tér vissza ha ütközik a másik taskkal (a szemesztert nem vizsgálja.) </returns>
		public bool HasIntersect( ITask other )
		{
			foreach( IInterval iv1 in timeIntervals )
			{
				foreach( IInterval iv2 in other.TimeIntervals )
				{
					if( iv1.HasIntersect( iv2 ) )
					{
						return true;
					}
				}
			}

			return false;
		}

		#endregion

		/// <summary>
		/// Konstruktor linq entitázsból.
		/// </summary>
		/// <param name="task">A linq entitázs</param>
		internal Task( TASK task )
		{
			name = task.NAME;
			hours = task.HOURS;
			semester = Engine.Instance().ConvertSemester( task.SEMESTER );
			id = task.ID;
		}


		/// <summary>
		/// Frissíti a megadott linq entitázs adatait.
		/// </summary>
		/// <param name="t">Az entitázs</param>
		/// <param name="fact">A kapcsolódó tárgy</param>
		/// <param name="name">A task neve.</param>
		/// <param name="hours">A task heti óraszáma.</param>
		/// <param name="type">A task típusa.</param>
		/// <param name="semester">A szemeszter típusa.</param>
		/// <param name="db">Az adatbáziskontextus.</param>
		internal static void UpdateLinqEntity( TASK t, IFact fact, string name, int hours, ITaskType type, SemesterType semester, TerhelesElosztoDBClassesDataContext db )
		{
			if( !( from row in db.FACTs where row.NEPTUN == fact.Neptun select row ).Any() )
			{
				throw new EngineException( "A feladathoz hozzárendelni kívánt tárgy nem létezik" );
			}

			t.NAME = name;
			t.TYPE = type.ID;
			t.FACT_NEPTUN = fact.Neptun;
			t.TEACHER = null;
			t.SEMESTER = Engine.Instance().Convert( semester );
			t.HOURS = hours;
		}

		private int id;
		private string name;
		private IFact relatedFact;
		private ITaskType type;
		private List<IInterval> timeIntervals;
		private List<ISkill> requiredSkills;
		private List<ITeacher> possibleTeachers;
		private ITeacher relatedTeacher;
		private int hours;
		private SemesterType semester;

		public override bool Equals( object obj )
		{
			if( obj is ITask )
			{
				ITask o = (ITask)( obj );
				return o.ID == id;
			}
			else
			{
				return base.Equals( obj );
			}
		}
	}
}
